/*
 * Motor.cpp
 *
 *  Created on: 18/10/2012
 *      Author: Ignacio Galvez
 */
#include "Motor.h"
#include "Pajaro.h"
#include "Bonificable.h"
#include "Caja.h"
#include "Cerdito.h"
#include "Huevo.h"
#include "Jugador.h"
#include "MonticuloDeHuevos.h"
#include "LineaEntradaPajarosVerticalDerecha.h"
#include "LineaEntradaPajarosVerticalIzquierda.h"
#include "Nivel.h"
#include <cmath>
#include <iostream>
#include <ctime>
// Motor::Motor(int numeroNivel, int cantidadDeJugadores, double timeout) :
// 		numeroNivel(numeroNivel), puntajeMaximo(0), puntajeActual(0), cantidadDeJugadores(
// 				cantidadDeJugadores), timeout(timeout), gano(false), perdio(
// 				false), superficie(10, 20), monticuloDeHuevos(NULL) {
// }

Motor::Motor(Nivel& nivel) {}

Motor::Motor() {
LineaEntradaPajarosVerticalDerecha* lineaDerecha = 
new LineaEntradaPajarosVerticalDerecha(400, 500);
LineaEntradaPajarosVerticalIzquierda* lineaIzquierda = 
new LineaEntradaPajarosVerticalIzquierda(400, 500);
lineasEntradaPajaros.push_back(lineaDerecha);
lineasEntradaPajaros.push_back(lineaIzquierda);
Cerdito* cerdito = new Cerdito(1, 210, 120);
cerditos.push_back(cerdito);
monticuloDeHuevos = new MonticuloDeHuevos(310,120);
timeout = 60;
gano = false;
perdio = false;
}

void Motor::ejecutarColisiones(double t) {
	const double deltaX = 50;
	const double deltaY = 50;
	std::list<Huevo*>::iterator itHuevos;
	std::list<Caja*>::iterator itCajas;
	std::list<Bonificable*>::iterator itBonificables;
	std::list<Pajaro*>::iterator itPajaros;
	std::list<Cerdito*>::iterator itCerditos;
	std::cout <<"iterando por huevos "<<std::endl;
	for (itHuevos = huevos.begin(); itHuevos != huevos.end(); ++itHuevos) {
		if (*itHuevos != NULL) {
		if ((*itHuevos)->haImpactado()){ 
			delete *itHuevos;
			//huevos.erase(itHuevos);
			*itHuevos = NULL;
		}
		else {
			if (superficie.recibirImpacto((*itHuevos)->getPosicionX(),
				(*itHuevos)->getPosicionY())) (*itHuevos)->explotar();			
			for (itCajas = cajas.begin(); itCajas != cajas.end(); ++itCajas) {				
				if ((fabs((*itHuevos)->getPosicionX() - (*itCajas)->getPosicionX())
						<= deltaX)
						&& (fabs(
								(*itHuevos)->getPosicionY()
										- (*itCajas)->getPosicionY()) <= deltaY)) 
					puntajeActual += (*itCajas)->bonificar();
					(*itHuevos)->daniar((*itCajas));
					if ((*itCajas)->getPuntosDeVida() == 0) {
						delete *itCajas;
					}
				
			}
			for (itBonificables = bonificables.begin();
					itBonificables != bonificables.end(); ++itBonificables) {
				if ((fabs(
						(*itHuevos)->getPosicionX()
								- (*itBonificables)->getPosicionX()) <= deltaX)
						&& (fabs(
								(*itHuevos)->getPosicionY()
										- (*itBonificables)->getPosicionY())
								<= deltaY)) {
					puntajeActual += (*itBonificables)->bonificar();
					delete *itBonificables;
				}
			}
			for (itPajaros = pajaros.begin(); itPajaros != pajaros.end();
					++itPajaros) {
					if (*itPajaros != NULL) {
					(*itHuevos)->daniar((*itPajaros));
					 if ((*itPajaros)->getPuntosDeVida() == 0) {
					 	delete *itPajaros;
					 	*itPajaros = NULL;
					}
					}
				}
			}
		}//
	}
	
	std::cout<<"no son los huevos, iterando por pajaros"<<std::endl;
	for (itPajaros = pajaros.begin(); itPajaros != pajaros.end(); ++itPajaros) {
		if (*itPajaros != NULL) {
		if ((*itPajaros)->haImpactado()){ 
			delete *itPajaros;
			//pajaros.erase(itPajaros);
			*itPajaros = NULL;
		}
		else {
			if (superficie.recibirImpacto((*itPajaros)->getPosicionX(),
					(*itPajaros)->getPosicionY()))
				(*itPajaros)->rebotar(t);
			for (itCajas = cajas.begin(); itCajas != cajas.end(); ++itCajas) {
				if ((fabs((*itPajaros)->getPosicionX() - (*itCajas)->getPosicionX())
						<= deltaX)
						&& (fabs(
								(*itPajaros)->getPosicionY()
										- (*itCajas)->getPosicionY()) <= deltaY)) {
					(*itPajaros)->daniar((*itCajas));
					delete *itPajaros;
					pajaros.erase(itPajaros);
					if ((*itCajas)->getPuntosDeVida() == 0) {
						delete *itCajas;
					}
				}
			}
			for (itBonificables = bonificables.begin();
					itBonificables != bonificables.end(); ++itCajas) {
				if ((fabs(
						(*itPajaros)->getPosicionX()
								- (*itBonificables)->getPosicionX()) <= deltaX)
						&& (fabs(
								(*itPajaros)->getPosicionY()
										- (*itBonificables)->getPosicionY())
								<= deltaY)) {
					delete *itBonificables;
				}
			}
			
			std::cout<<"no son los pajaros"<<std::endl;
			for (itCerditos = cerditos.begin(); itCerditos != cerditos.end();
					++itCerditos) {
				if ((fabs(
						(*itPajaros)->getPosicionX()
								- (*itCerditos)->getPosicionX()) <= deltaX)
						&& (fabs(
								(*itPajaros)->getPosicionY()
										- (*itCerditos)->getPosicionY()) <= deltaY)) {
					(*itPajaros)->daniar((*itCerditos));
				}
			}
		}//
		}
	}
}
void Motor::generarPajaros( double ticks) {
std::cout <<"generando pajaros" <<std::endl;
std::list<LineaDeEntradaPajaros*>::iterator it;
for (it = lineasEntradaPajaros.begin(); it != lineasEntradaPajaros.end(); 
	++ it) {
//	Pajaro* pajaro = lineasEntradaPajaros.back()->generarPajaro(ticks);
	Pajaro* pajaro = (*it)->generarPajaro(ticks);
	pajaros.push_back(pajaro);
}
std::cout <<" pajaros generados" <<std::endl;
}


// void Motor::generarPajaros() {
// std::cout <<"generando pajaros" <<std::endl;
// std::list<LineaDeEntradaPajaros*>::iterator it;
// for (it = lineasEntradaPajaros.begin(); it != lineasEntradaPajaros.end(); 
// 	++ it) {
// //	Pajaro* pajaro = lineasEntradaPajaros.back()->generarPajaro(ticks);
// 	Pajaro* pajaro = (*it)->generarPajaro(time(NULL));
// 	pajaros.push_back(pajaro);
// }
// std::cout <<" pajaros generados" <<std::endl;
// }

void Motor::realizarDisparos() {
	std::list<Huevo*> huevosNuevos;
	std::list<Huevo*>::iterator itHuevosNuevos;
	std::list<Cerdito*>::iterator itCerditos;
	for (itCerditos = cerditos.begin(); itCerditos != cerditos.end();
			++itCerditos) {
		Cerdito::incrementarTiempoActual();
		if ((*itCerditos)->dispara()) {
			huevosNuevos = (*itCerditos)->disparar();
		}
		for (itHuevosNuevos = huevosNuevos.begin();
				itHuevosNuevos != huevosNuevos.end(); ++itHuevosNuevos) {
			huevos.push_front((*itHuevosNuevos));
		}
	}
}

bool Motor::perdioNivel() {
	return perdio;
}
bool Motor::ganoNivel() {
	return gano;
}


void Motor::actualizarEstado(double ticks ) {
	std::list<Jugador*>::iterator itJugadores;
	std::list<Huevo*>::iterator itHuevos;
	std::list<Pajaro*>::iterator itPajaros;
	std::cout <<"llama a generar pajaros"<<std::endl;
	if (((int )ticks % 30 )== 0)
	generarPajaros( ticks );
	std::cout<<"realiza los disparos"<<std::endl;
	realizarDisparos();
	std::cout<<"moviendo los huevos"<<std::endl;
	for (itHuevos = huevos.begin(); itHuevos != huevos.end(); ++itHuevos) {
		if (*itHuevos != NULL)
		(*itHuevos)->mover(ticks);
	}
	std::cout<<"moviendo los pajaros"<<std::endl;
	for (itPajaros = pajaros.begin(); itPajaros != pajaros.end(); ++itPajaros) {
		if (*itPajaros != NULL)
		(*itPajaros)->mover(ticks);
	}
	std::cout<<"ejecuta colisiones"<<std::endl;
	ejecutarColisiones(ticks);
	std::cout<<"ejecuto colisiones "<<std::endl;
	itJugadores = jugadores.begin();
	 while ((itJugadores != jugadores.end())&&( !perdio))
	{
	perdio = !((*itJugadores)->estaEnJuego());
	++itJugadores;
	}
	if (!perdio) perdio = (monticuloDeHuevos->getPuntosDeVida() == 0);
	if (!perdio) gano = (ticks == timeout * 10);
}

void Motor::iniciar() {
	double tiempoActual = 0;
	while ((tiempoActual < timeout) && (!perdio)) {
		actualizarEstado(tiempoActual);
		tiempoActual++;
	}
}

void Motor::bonificar() {
}

// void Motor::eliminarJugadores() {
// 	std::list<Jugador*>::iterator it;
// 	for (it = jugadores.begin(); it != jugadores.end(); ++it) {
// 		if (!(*it)->estaEnJuego()) {
// 			delete *it;
// 		}
// 	}
// }



std::list<Pajaro*>  Motor::getPajaros(){
	return pajaros;
}

std::list<Huevo*> Motor:: getHuevos(){
	return huevos;
}

std::list<Cerdito*>  Motor::getCerditos(){
	return cerditos;
}

std::list<Caja*>  Motor::getCajas(){
	return cajas;
}

std::list<Bonificable*>  Motor::getBonificables(){
	return bonificables;
}

MonticuloDeHuevos* Motor::getMonticuloDeHuevos() {
	return monticuloDeHuevos;
}


Jugador* Motor::agregarJugador(std::string& nombreJugador) {
	Jugador* jugador = new Jugador(nombreJugador,cerditos.back(),0);
	jugadores.push_back(jugador);
	return jugador;
}

Motor::~Motor() {}
